package com.zggk.framework.utils;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.platform.framework.entity.file.BaseFileEntity;
import com.platform.framework.service.BaseServiceImpl;
import com.zggk.framework.service.file.BaseFileEntityService;
import com.zggk.framework.utils.assets.ImportNumberStringUtils;

import io.minio.MinioClient;

@Component
public class FileUtils extends BaseServiceImpl{
	
	
	private final Logger log = LoggerFactory.getLogger(FileUtils.class);
	
	private static volatile MinioClient minioClient = null;  
	
	
	//报告生成的路径文件 变量
	public static String docpath;
	
	public static String freportUrl;
	public static String ctmsUrl;
	public static String minioUrl;    
	public static String minioUsername; 
	public static String minioPassword; 
	public static String qftxUrl;
	@Value("${system.minioUrl}")  
	private String minioUrlTmp;
	
	@Value("${system.minioUsername}")  
	private String minioUsernameTmp;
	
	@Value("${system.minioPassword}")  
	private String minioPasswordTmp;
	 
	
	@Autowired
	BaseFileEntityService baseFileEntityService;
	
	
	@PostConstruct  
	public void init() throws Exception {  
		minioUrl = minioUrlTmp;  
		minioUsername = minioUsernameTmp;
		minioPassword = minioPasswordTmp;
	}  
	
	
	
	public static MinioClient getInstance() {
        if (minioClient == null) {  
            synchronized (FileUtils.class) {  
                if (minioClient == null) {  
                	try {
                		//new FileUtils(); 
                		minioClient = new MinioClient(minioUrl,minioUsername,minioPassword);
					} catch (Exception e) {
						e.printStackTrace();
					}
                }  
            }  
        }  
        return minioClient;  
    }  
	
	
	/**
	 * 
	  * 描述：文件上传工具类 .
	  * @author 王求卿[wangqiuqing] Tel18101037995
	  * @param file
	  * @param request
	  * @param response
	  * @return 文件ID，文件位置路径。 失败返回false
	  * @throws UnsupportedEncodingException
	 */
	public  String uploadCommonFile(MultipartFile file, HttpServletRequest request,
			HttpServletResponse response) throws UnsupportedEncodingException {
		ReturnMessage msg = new ReturnMessage();
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		try {
			InputStream fileInput = file.getInputStream();
			ByteArrayOutputStream fileOut = new ByteArrayOutputStream();
			byte[] b = new byte[1024];
			int len;
			while ((len = fileInput.read(b)) > -1) {
				fileOut.write(b, 0, len);
			}
			fileOut.flush();
			// 获得文件名
			String fileName = file.getOriginalFilename();
			String path = "我的文档";
			// 获取文件后缀名并转化为小写，用于后续比较
			String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase();
			InputStream thumbsImg = null;
			String md5 = DigestUtils.md5Hex(file.getInputStream());

			String bucket = "lwzx";
			String objectName = "";
			BaseFileEntity existBaseFileEntity = baseFileEntityService.isExistFile(md5,this.getUserCode());
			
			if (existBaseFileEntity == null) {
				MinioClient minioClient = FileUtils.getInstance();
				boolean isExist = minioClient.bucketExists(bucket);
				
				if (isExist) {
					log.info("Bucket already exists.");
				} else {
					// Make a new bucket called asiatrip to hold a zip file of photos.
					minioClient.makeBucket(bucket);
				}
				String user = null;
				if(ImportNumberStringUtils.stringFilter(this.getUserCode())) {
					user = ImportNumberStringUtils.replaceSpecialStr(this.getUserCode()).toLowerCase();					
				}else {
					user = this.getUserCode().toLowerCase();
				}
				boolean isUser = minioClient.bucketExists(user);
				if (isUser) {
					log.info("Bucket already exists.");
				} else {
					// Make a new bucket called asiatrip to hold a zip file of photos.
					minioClient.makeBucket(user);
				}
				// Upload file to the bucket with putObject
				log.info("uploading file. file Size：" + file.getSize());
				String newFileName = getUUID() + "." + fileType;
				// 上传文件,如果是图片类型,处理缩略图上传到"我的图片/thumbs"
				if (FileUtils.isImage(fileType)) {
					path = "我的图片";
					InputStream thumInput = new BufferedInputStream(new ByteArrayInputStream(fileOut.toByteArray()));
					thumbsImg = ThumbnailatorUtils.getThumbsImg(thumInput);// 获取缩略图流
					thumInput.close();
					// 创建目录thumbs
					objectName = path + "/" + this.getUserCode() + "/thumbs/" + newFileName;
					minioClient.putObject(bucket, objectName, thumbsImg, thumbsImg.available(),
							"application/octet-stream");
					thumbsImg.close();
				}
				InputStream orgInput = new BufferedInputStream(new ByteArrayInputStream(fileOut.toByteArray()));

				objectName = path + "/" + this.getUserCode() + "/" + newFileName;				
				minioClient.putObject(bucket, objectName, orgInput, orgInput.available(), "application/octet-stream");
				fileInput.close();
				BaseFileEntity baseFileEntity = new BaseFileEntity();
				baseFileEntity.setId(getUUID());
				baseFileEntity.setFileName(fileName);
				baseFileEntity.setFileNewName(newFileName);
				baseFileEntity.setFileDirectory("lwzx");
				baseFileEntity.setFilePath(path + "/" + this.getUserCode() + "/");
				baseFileEntity.setAbsolutePath(
						minioClient.getObjectUrl("lwzx", path + "/" + this.getUserCode() + "/" + newFileName));
				baseFileEntity.setFileSize(file.getSize());
				baseFileEntity.setFileType(fileType);
				baseFileEntity.setFileMd5(md5);
				baseFileEntity.setCreateUserCode(this.getUserCode());
				baseFileEntity.setCreateUserName(this.getUserEntity().getName());
				baseFileEntity.setCreateTime(new Date());
				baseFileEntity.setUpdateUserCode(this.getUserCode());
				baseFileEntity.setUpdateUserName(this.getUserEntity().getName());
				baseFileEntityService.saveFileInfo(baseFileEntity);
			} else {
				objectName = path + "/" + this.getUserCode() + "/" + existBaseFileEntity.getFileNewName();
				existBaseFileEntity.setFileName(fileName);
				baseFileEntityService.saveFileInfo(existBaseFileEntity);
			}

			Map<String, String> taskParams = Maps.newHashMap();
			taskParams.put("fileName", file.getOriginalFilename());//原始文件名称
			taskParams.put("ctmsUrl", ctmsUrl);
			taskParams.put("fileLocation", objectName);
			taskParams.put("fileSize", String.valueOf(file.getSize()));
			taskParams.put("fileStorage", "MINIO");
			taskParams.put("userCode", this.getUserCode());
			taskParams.put("userName", this.getUserEntity().getName());
			msg.setData(taskParams);
			msg.setStatus("true");
			msg.setInfo(file.getOriginalFilename() + "上传成功");
			log.info(file.getOriginalFilename() + " is uploaded successfully");
		} catch (Exception e) {
			e.printStackTrace();
			msg.setStatus("false");
			msg.setData(e.toString());
		}
		return JSONObject.toJSONString(msg);
	}


	
	
	
	/**
	 * 读取文件  返回文件字符串内容
	  * @Description .
	  * @author 李增冰[lizengbing] Tel13807031023
	  * @param file
	  * @return
	 */
	public static String readFile(File file) {
		String result="";
		if(file.length()!=0) {
			BufferedReader bfReader =null;
			try {
				InputStream in=new FileInputStream(file);
				bfReader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
				String inString ="";
		    	while((inString = bfReader.readLine())!= null){
		    		result+=inString;
		    	}
			} catch (Exception e) {
				e.printStackTrace();;
			}finally {
				try {
					bfReader.close();
				} catch (Exception e2) {
					e2.printStackTrace();
				}
			}
			
		}
		return result;
	}
	
	
	/**
	 * 判断是否是图片类型
	 * 
	 * @param type
	 * @return
	 */
	public static boolean isImage(String type) {
		type = type.toLowerCase();
		if (type != null
				&& (type.equals("jpg") || type.equals("gif")
						|| type.equals("png") || type.equals("jpeg")
						|| type.equals("bmp") || type.equals("wbmp")
						|| type.equals("ico") || type.equals("jpe"))) {
			return true;
		}
		return false;
	}
	
	/**
	 * @Description 删除csv文件的方法
	 * @author 张立增[zhanglizeng] Tel：18860126570
	 * @createDate 2018年7月12日 下午2:18:37
	 */
	 public static void deleteFile(String fileName) {
		try {
		    File file = new File(fileName);
	        if (file.exists() && file.isFile()) {
	            if (file.delete()) {
	                logger.info("[delete] csv文件:"+fileName+"成功！");
	            } else {
	                logger.info("[delete] csv文件:"+fileName+"失败！");
	            }
	        } else {
	        	logger.info("[delete] csv文件:"+fileName+"不存在！");
	        }
		} catch (Exception e) {
			logger.info("[delete] csv文件:"+fileName+"异常！");   
		}
    }
	 



	 public static String getFile(InputStream in) {
			String result="";
				BufferedReader bfReader =null;
				try {
					bfReader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
					String inString ="";
			    	while((inString = bfReader.readLine())!= null){
			    		result+=inString;
			    	}
				} catch (Exception e) {
					e.printStackTrace();;
				}finally {
					try {
						bfReader.close();
					} catch (Exception e2) {
						e2.printStackTrace();
					}
				}
			return result;
	}
	 
	/**
	 * @Description 检查不用解析的文件名格式是否符合上传要求
	 * @author 张立增
	 * @Date 2019年5月15日 下午1:20:32
	 */
	public static boolean checkFileNameNoParse(String fileName) {
		try {
			if(!StringUtils.isEmpty(fileName)) {
				String fileEnd = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase();//文件结尾类型
			    if("xls".equals(fileEnd) || "xlsx".equals(fileEnd) || "doc".equals(fileEnd) || "docx".equals(fileEnd) || "pdf".equals(fileEnd) || "txt".equals(fileEnd) || "ppt".equals(fileEnd) || "pptx".equals(fileEnd)) {
			    	return true;
			    }
			}
			return false;
		} catch (Exception e) {
			return false;
		}
	}
	
	/**
	 * @Description 检查解析的文件名格式是否符合上传要求
	 * @author 张立增
	 * @Date 2019年5月15日 下午1:43:49
	 */
	public static boolean checkFileNameParse(String fileName) {
		try {
			if(!StringUtils.isEmpty(fileName)) {
				String fileEnd = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase();//文件结尾类型
			    if("xls".equals(fileEnd) || "xlsx".equals(fileEnd)) {
			    	return true;
			    }
			}
			return false;
		} catch (Exception e) {
			return false;
		}
	}
	
	/**
	 * @Description 检查上传的图片格式是否符合上传要求
	 * @author 张立增
	 * @Date 2019年5月15日 下午2:56:03
	 */
	public static boolean checkPictureName(String fileName) {
		try {
			if(!StringUtils.isEmpty(fileName)) {
				String fileEnd = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase();//文件结尾类型
			    if("png".equals(fileEnd) || "bmp".equals(fileEnd) || "jpg".equals(fileEnd) || "gif".equals(fileEnd)) {
			    	return true;
			    }
			}
			return false;
		} catch (Exception e) {
			return false;
		}
	}
	
	/**
	 * @Description 过滤特殊字符的方法,保留+-.()五个字符
	 * @author 张立增
	 * @Date 2019年7月13日 上午11:39:24
	 */
	public static String regStr(String str) {
		String regEx="[`~!@#$%^&*=|{}':;',\\[\\]<>/?~！@#￥%……&*——|{}【】‘；：”“’。，、？]"; 
		Pattern p = Pattern.compile(regEx); 
		Matcher m = p.matcher(str);
		return m.replaceAll("").replaceAll("\\s*", "");
	}

	/**
	 * 
	 * @Description 根据输入流得到Workbook的方法
	 * @author 张立增[zhanglizeng] Tel：18860126570
	 * @createDate 2018年4月25日 上午10:46:34
	 */
	public static Workbook getWorkBook(InputStream in,String fileName) throws Exception  {
		Workbook workbook = null;
		try {
		    if(fileName.endsWith("xls")){        //根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
	            workbook = new HSSFWorkbook(in);
	        }else if(fileName.endsWith("xlsx")){ //2007 及2007以上
	            workbook = new XSSFWorkbook(in); //2003
	        }
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return workbook;
	}

	/**
	 * 
	 * @Description 解析cell的方法
	 * @author 张立增[zhanglizeng] Tel：18860126570
	 * @createDate 2018年4月25日 下午1:08:17
	 */
	public static String parseCell(Cell cell) {
		String cellValue = "";  
		SimpleDateFormat sdf = new  SimpleDateFormat("yyy-MM-dd");//日期格式化  
		if(cell != null && !"".equals(cell)){
			switch (cell.getCellType()){
	        case Cell.CELL_TYPE_NUMERIC:   //数字
	             if("General".equals(cell.getCellStyle().getDataFormatString())) {  
	            	 cellValue = cell.getNumericCellValue()+"";     
                 }else if("m/d/yy".equals(cell.getCellStyle().getDataFormatString())) {  
                	 cellValue = sdf.format(cell.getDateCellValue());  
                 }else if(HSSFDateUtil.isCellDateFormatted(cell)){  
                     Date date = cell.getDateCellValue();  
                     cellValue = sdf.format(date);                 
                 }else {  
                	 cellValue = cell.getNumericCellValue()+"";  
                 }              
	            break;
	        case Cell.CELL_TYPE_STRING: //字符串
	            cellValue = String.valueOf(cell.getStringCellValue());
	            break;
	        case Cell.CELL_TYPE_BOOLEAN: //Boolean
                cellValue = String.valueOf(cell.getBooleanCellValue());
                break;
            case Cell.CELL_TYPE_FORMULA: //公式
                cellValue = String.valueOf(cell.getNumericCellValue());          
                break;
            case Cell.CELL_TYPE_BLANK: //空值
                cellValue = "";
                break;
            case Cell.CELL_TYPE_ERROR: //故障
                cellValue = "";
                break;
            default:
                cellValue = "";
                break;   
		    }
		}
        return cellValue;
	}
	
}
